
// 音频重采样处理工具
export async function resampleAudio(audioBlob: Blob, targetSampleRate: number = 8000): Promise<Blob> {
    const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
    const arrayBuffer = await audioBlob.arrayBuffer();
    const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

    const offlineCtx = new OfflineAudioContext(
        1, // 单声道
        audioBuffer.duration * targetSampleRate,
        targetSampleRate
    );

    const source = offlineCtx.createBufferSource();
    source.buffer = audioBuffer;
    source.connect(offlineCtx.destination);
    source.start();

    const renderedBuffer = await offlineCtx.startRendering();
    const channelData = renderedBuffer.getChannelData(0);

    // 将音频数据转换为WAV格式
    const wavBuffer = createWavBuffer(channelData, targetSampleRate);
    return new Blob([wavBuffer], { type: 'audio/wav' });
}

// 创建WAV文件格式的Buffer
function createWavBuffer(samples: Float32Array, sampleRate: number): ArrayBuffer {
    const buffer = new ArrayBuffer(44 + samples.length * 2);
    const view = new DataView(buffer);

    // WAV Header
    writeString(view, 0, 'RIFF');
    view.setUint32(4, 36 + samples.length * 2, true);
    writeString(view, 8, 'WAVE');
    writeString(view, 12, 'fmt ');
    view.setUint32(16, 16, true);
    view.setUint16(20, 1, true); // PCM
    view.setUint16(22, 1, true); // 单声道
    view.setUint32(24, sampleRate, true);
    view.setUint32(28, sampleRate * 2, true);
    view.setUint16(32, 2, true);
    view.setUint16(34, 16, true);
    writeString(view, 36, 'data');
    view.setUint32(40, samples.length * 2, true);

    // 写入采样数据
    const volume = 0.8;
    let index = 44;
    for (let i = 0; i < samples.length; i++) {
        view.setInt16(index, samples[i] * 0x7FFF * volume, true);
        index += 2;
    }

    return buffer;
}

// 写入字符串到DataView
function writeString(view: DataView, offset: number, string: string): void {
    for (let i = 0; i < string.length; i++) {
        view.setUint8(offset + i, string.charCodeAt(i));
    }
}